package guiClasses;

import java.util.Observer;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import objectClasses.Database;
import objectClasses.Draft;


public class DraftPanel extends GenericPanel{

	private Draft my_draft;
	private JPanel my_drawDown;

	private static final Dimension SQUARE_SIZE = new Dimension(15,15);
	private static final int SIZE = 32;

	/**
	@wbp.parser.constructor
	*/
	public DraftPanel(final Observer the_o_er) {
		super(the_o_er);
		my_draft = new Draft();
		createPanel();
	}

	public DraftPanel(final Observer the_o_er, final Draft the_draft) {
		super(the_o_er);
		my_draft = the_draft;
		createPanel();
	}


	private void createPanel() {
		my_panel.setPreferredSize(new Dimension(850,850));
		my_panel.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.black));

		JLabel spaceLabel = new JLabel();
		spaceLabel.setPreferredSize(SQUARE_SIZE);
		my_panel.add(spaceLabel, GBC.GBCGen(0,0,1,1));
		spaceLabel = new JLabel();
		spaceLabel.setPreferredSize(SQUARE_SIZE);
		my_panel.add(spaceLabel, GBC.GBCGen(0,0,0,2));
		my_panel.add(ThreadingColorPanel(), GBC.GBCGen(0,0, 1, 2));
		spaceLabel = new JLabel();
		spaceLabel.setPreferredSize(SQUARE_SIZE);
		my_panel.add(spaceLabel, GBC.GBCGen(0,0,1,3));
		my_panel.add(ThreadingPanel(), GBC.GBCGen(0, 0, 1, 4));
		spaceLabel = new JLabel();
		spaceLabel.setPreferredSize(SQUARE_SIZE);
		my_panel.add(spaceLabel, GBC.GBCGen(0,0,1,5));
		spaceLabel = new JLabel();
		spaceLabel.setPreferredSize(SQUARE_SIZE);
		my_panel.add(spaceLabel, GBC.GBCGen(0,0,6,1));
		my_panel.add(TreadingColorPanel(), GBC.GBCGen(0, 0, 5, 6));
		spaceLabel = new JLabel();
		spaceLabel.setPreferredSize(SQUARE_SIZE);
		my_panel.add(spaceLabel, GBC.GBCGen(0,0,4,6));
		my_panel.add(TreadingPanel(), GBC.GBCGen(0,0,3,6));
		spaceLabel = new JLabel();
		spaceLabel.setPreferredSize(SQUARE_SIZE);
		my_panel.add(spaceLabel, GBC.GBCGen(0,0,2,6));
		my_panel.add(TieupPanel(), GBC.GBCGen(0, 0, 3, 4));	
		my_drawDown = drawDownPanel();
		my_panel.add(my_drawDown, GBC.GBCGen(0,0,1,6));
		GridBagConstraints c = GBC.GBCGen(0, 0, 0, 7);
		c.gridwidth = 7;
		c.anchor = GridBagConstraints.PAGE_END;
		my_panel.add(buttonPanel(), c);

		my_panel.setVisible(true);

	}

	private JPanel ThreadingColorPanel() {
		JPanel temp = new JPanel();
		GridBagConstraints c = null;
		temp.setLayout(new GridBagLayout());
		for(int i = 0; i < SIZE; i++) {
			final int the_warp = i;
			c = GBC.GBCGen(0, 0, i, 0);
			final JLabel tempLabel = new JLabel();
			tempLabel.setPreferredSize(SQUARE_SIZE);
			tempLabel.setOpaque(true);
			tempLabel.setBackground(my_draft.getThreadingColor(i));
			if(i == 0) {
				tempLabel.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.black));
			} else{
				tempLabel.setBorder(BorderFactory.createMatteBorder(1,0,1,1,Color.black));
			} 
			tempLabel.addMouseListener(new MouseListener() {

				@Override
				public void mouseClicked(MouseEvent arg0) {
					Color tempColor = JColorChooser.showDialog(tempLabel, "Select a warp thread color", 
							my_draft.getThreadingColor(the_warp));
					my_draft.setThreadingColor(tempColor, the_warp);
					tempLabel.setBackground(tempColor);

					my_panel.remove(my_drawDown);
					my_drawDown = drawDownPanel();
					my_panel.add(my_drawDown, GBC.GBCGen(0,0,1,6));
					my_drawDown.revalidate();
					my_panel.repaint();

				}

				@Override
				public void mouseEntered(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mouseExited(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mousePressed(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mouseReleased(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

			});
			temp.add(tempLabel, c);
		}
		return temp;
	}

	private JPanel ThreadingPanel() {
		JPanel temp = new JPanel();
		temp.setLayout(new GridBagLayout());
		for(int i = 0; i < SIZE; i++) { 
			temp.add(innerThreadingPanel(i), GBC.GBCGen(0, 0, i, 0));
		}

		return temp;
	}

	private JPanel TreadingColorPanel() {
		JPanel temp = new JPanel();
		GridBagConstraints c = null;
		temp.setLayout(new GridBagLayout());

		for(int i = 0; i < SIZE; i++) {
			c = GBC.GBCGen(0, 0, 0, i);
			final int the_weft = i;
			final JLabel tempLabel = new JLabel();
			tempLabel.setPreferredSize(SQUARE_SIZE);
			tempLabel.setOpaque(true);
			tempLabel.setBackground(my_draft.getTreadingColor(i));

			if(i == 0) {
				tempLabel.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.black));
			} else{
				tempLabel.setBorder(BorderFactory.createMatteBorder(0,1,1,1,Color.black));
			} 

			tempLabel.addMouseListener(new MouseListener() {

				@Override
				public void mouseClicked(MouseEvent arg0) {
					Color tempColor = JColorChooser.showDialog(tempLabel, "Select a weft thread color", 
							my_draft.getTreadingColor(the_weft));
					my_draft.setTreadingColor(tempColor, the_weft);
					tempLabel.setBackground(tempColor);
					my_panel.remove(my_drawDown);
					my_drawDown = drawDownPanel();
					my_panel.add(my_drawDown, GBC.GBCGen(0,0,1,6));
					my_drawDown.revalidate();
					my_panel.repaint();

				}

				@Override
				public void mouseEntered(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mouseExited(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mousePressed(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mouseReleased(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

			});
			temp.add(tempLabel, c);
		}

		return temp;
	}

	private JPanel TreadingPanel() {
		JPanel temp = new JPanel();
		temp.setLayout(new GridBagLayout());
		for(int i = 0; i < SIZE; i++) { 
			temp.add(innerTreadingPanel(i), GBC.GBCGen(0, 0, 0, i));
		}
		return temp;
	}

	private JPanel innerTreadingPanel(int the_i) {
		final JPanel innerPanel = new JPanel();
		innerPanel.setLayout(new GridBagLayout());
		for(int j = 0; j < 6; j++) { // sets the inner panels
			final JLabel tempLabel = new JLabel();
			tempLabel.setPreferredSize(SQUARE_SIZE);
			tempLabel.setOpaque(true);
			if(the_i == 0 && j == 0) {
				tempLabel.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.black));
			} else if (the_i == 0 && j != 0){
				tempLabel.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 1, Color.black));
			} else if (the_i != 0 && j == 0){
				tempLabel.setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, Color.black));
			} else {
				tempLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 1, Color.black));
			}
			if (j == my_draft.getPedal(the_i)) {
				tempLabel.setBackground(Color.black);
			} else {
				tempLabel.setBackground(Color.white);
			}
			final int the_pedal = j;
			final int the_weft = the_i;
			tempLabel.addMouseListener(new MouseListener() {

				@Override
				public void mouseClicked(MouseEvent arg0) {
					tempLabel.setBackground(Color.black);
					my_draft.setPedal(the_pedal, the_weft);
					for (int i = 0; i < 6; i++){
						if(i != the_pedal) {
							innerPanel.getComponent(i).setBackground(Color.white);
						}
					}
					my_panel.remove(my_drawDown);
					my_drawDown = drawDownPanel();
					my_panel.add(my_drawDown, GBC.GBCGen(0,0,1,6));
					my_drawDown.revalidate();
					my_panel.repaint();
				}

				@Override
				public void mouseEntered(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mouseExited(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mousePressed(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mouseReleased(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

			});
			innerPanel.add(tempLabel, GBC.GBCGen(0,0,j,0));

		}
		return innerPanel;
	} // end innerTreadingPanel

	private JPanel innerThreadingPanel(int the_i) {
		final JPanel innerPanel = new JPanel();
		innerPanel.setLayout(new GridBagLayout());
		for(int j = 0; j < 4; j++) { // sets the inner panels
			final JLabel tempLabel = new JLabel();
			tempLabel.setPreferredSize(SQUARE_SIZE);
			tempLabel.setOpaque(true);
			if(the_i == 0 && j == 0) {
				tempLabel.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.black));
			} else if (the_i == 0 && j != 0){
				tempLabel.setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, Color.black));
			} else if (the_i != 0 && j == 0){
				tempLabel.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 1, Color.black));
			} else {
				tempLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 1, Color.black));
			}
			if (j == my_draft.getHarness(the_i)) {
				tempLabel.setBackground(Color.black);
			} else {
				tempLabel.setBackground(Color.white);
			}
			final int the_harness = j;
			final int the_warp = the_i;
			tempLabel.addMouseListener(new MouseListener() {

				@Override
				public void mouseClicked(MouseEvent arg0) {
					tempLabel.setBackground(Color.black);
					my_draft.setHarness(the_harness, the_warp);
					for (int i = 0; i < 4; i++){
						if(i != the_harness) {
							innerPanel.getComponent(i).setBackground(Color.white);
						}
					}

					my_panel.remove(my_drawDown);
					my_drawDown = drawDownPanel();
					my_panel.add(my_drawDown, GBC.GBCGen(0,0,1,6));
					my_drawDown.revalidate();
					my_panel.repaint();
				}

				@Override
				public void mouseEntered(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mouseExited(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mousePressed(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mouseReleased(MouseEvent arg0) {
					// TODO Auto-generated method stub

				}

			});
			innerPanel.add(tempLabel, GBC.GBCGen(0,0,0,j));
		}
		return innerPanel;
	}

	private JPanel TieupPanel() {
		JPanel temp = new JPanel();
		temp.setLayout(new GridBagLayout());
		for(int i = 0; i < 6; i++) {
			for(int j = 0; j < 4; j++) {
				final int the_pedal = i;
				final int the_harness = j;
				final JLabel tempLabel = new JLabel();
				tempLabel.setPreferredSize(SQUARE_SIZE);
				tempLabel.setOpaque(true);
				if(i == 0 && j == 0) {
					tempLabel.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.black));
				} else if (i == 0 && j != 0){
					tempLabel.setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, Color.black));
				} else if (i != 0 && j == 0){
					tempLabel.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 1, Color.black));
				} else {
					tempLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 1, Color.black));
				}
				if(my_draft.getTieup(the_pedal, the_harness)) {
					tempLabel.setBackground(Color.black);
				} else {
					tempLabel.setBackground(Color.white);
				}
				tempLabel.addMouseListener(new MouseListener()  {

					@Override
					public void mouseClicked(MouseEvent arg0) {
						if(!my_draft.getTieup(the_pedal, the_harness)) {
							tempLabel.setBackground(Color.black);
							my_draft.setTieup(the_pedal, the_harness);
						} else {
							tempLabel.setBackground(Color.white);
							my_draft.setTieup(the_pedal, the_harness);
						}
						my_panel.remove(my_drawDown);
						my_drawDown = drawDownPanel();
						my_panel.add(my_drawDown, GBC.GBCGen(0,0,1,6));
						my_drawDown.revalidate();
						my_panel.repaint();

					}

					@Override
					public void mouseEntered(MouseEvent arg0) {
						// TODO Auto-generated method stub

					}

					@Override
					public void mouseExited(MouseEvent arg0) {
						// TODO Auto-generated method stub

					}

					@Override
					public void mousePressed(MouseEvent arg0) {
						// TODO Auto-generated method stub

					}

					@Override
					public void mouseReleased(MouseEvent arg0) {
						// TODO Auto-generated method stub

					}

				});
				temp.add(tempLabel, GBC.GBCGen(0, 0, i, j));
			}
		}

		return temp;
	}

	private JPanel drawDownPanel() {
		JPanel temp = new JPanel();
		temp.setLayout(new GridBagLayout());
		for(int i = 0; i < SIZE; i++) {
			for(int j = 0; j < SIZE; j++) {
				final int the_weft = j;
				final int the_warp = i;
				final JLabel tempLabel = new JLabel();
				tempLabel.setPreferredSize(SQUARE_SIZE);
				tempLabel.setOpaque(true);
				// the warp thread is displayed
				if(my_draft.getTieup(my_draft.getPedal(the_weft), my_draft.getHarness(the_warp))) {
					tempLabel.setBackground(my_draft.getThreadingColor(the_warp));
					if(isTop(the_weft, the_warp) && isBottom(the_weft, the_warp)) {
						tempLabel.setBorder(BorderFactory.createMatteBorder(0,1,0,1, Color.black));

					} else if (!isTop(the_weft, the_warp) && isBottom(the_weft, the_warp)){
						tempLabel.setBorder(BorderFactory.createMatteBorder(1,1,0,1, Color.black));

					} else if (isTop(the_weft, the_warp) && !isBottom(the_weft, the_warp)){
						tempLabel.setBorder(BorderFactory.createMatteBorder(0,1,1,1, Color.black));
					} else {
						tempLabel.setBorder(BorderFactory.createMatteBorder(1,1,1,1, Color.black));
					}
				} else { // the weft thread is displayed
					tempLabel.setBackground(my_draft.getTreadingColor(the_weft));
					if((isLeft(the_weft, the_warp) || the_warp == 0) && (isRight(the_weft, the_warp) || the_warp >= (SIZE - 1))) {
						tempLabel.setBorder(BorderFactory.createMatteBorder(1,1,1,1, Color.black));

					} else if (!isLeft(the_weft, the_warp) && (isRight(the_weft, the_warp) || the_warp >= (SIZE - 1))){
						tempLabel.setBorder(BorderFactory.createMatteBorder(1,0,1,1, Color.black));

					} else if ((isLeft(the_weft, the_warp) || the_warp == 0) && !isRight(the_weft, the_warp)) {
						tempLabel.setBorder(BorderFactory.createMatteBorder(1,1,1,0, Color.black));

					} else {
						tempLabel.setBorder(BorderFactory.createMatteBorder(1,0,1,0, Color.black));
					}
				}


				temp.add(tempLabel, GBC.GBCGen(0, 0, i, j));
			}
		}

		return temp;
	}

	private boolean isTop(int the_weft, int the_warp) {
		return the_weft > 0 && my_draft.getTieup(my_draft.getPedal(the_weft - 1), my_draft.getHarness(the_warp));
	}
	private boolean isBottom(int the_weft, int the_warp) {
		return the_weft < (SIZE - 1) && my_draft.getTieup(my_draft.getPedal(the_weft + 1), my_draft.getHarness(the_warp)); 
	}
	private boolean isLeft(int the_weft, int the_warp) {
		return the_warp > 0 && my_draft.getTieup(my_draft.getPedal(the_weft), my_draft.getHarness(the_warp - 1)); 
	}
	private boolean isRight(int the_weft, int the_warp) {
		return the_warp < (SIZE - 1) && my_draft.getTieup(my_draft.getPedal(the_weft), my_draft.getHarness(the_warp + 1)); 
	}

	private JPanel buttonPanel() {
		JPanel temp = new JPanel();
		temp.setLayout(new GridBagLayout());
		JButton clearButton = new JButton("Clear");
		clearButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
//				my_draft = new Draft();
//				my_panel.remove(my_drawDown);
//				my_drawDown = drawDownPanel();
//				my_panel.add(my_drawDown, GBC.GBCGen(0,0,1,6));
//				my_drawDown.revalidate();
//				my_panel.revalidate();
//				my_panel.repaint();

				setChanged();
				notifyObservers(new DraftPanel(my_o_ver).getPanel());
				
			}

		});
		GridBagConstraints c = GBC.GBCGen(0, 0, 0, 0);
		c.anchor = GridBagConstraints.EAST;
		temp.add(clearButton, c);
		JButton submitButton = new JButton("Submit");
		submitButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				setChanged();
				notifyObservers(new EntryPanel(my_o_ver, my_draft).getPanel());
				Database.printAllEntries();	
				Database.saveFile();
			}

		});
		c = GBC.GBCGen(0,0,1,0);
		c.anchor = GridBagConstraints.WEST;
		temp.add(submitButton, c);

		return temp;
	}
	private JPanel getDrawDown(){
		return my_drawDown;
	}
	/**
	 * 
	 * @param the_o_ver
	 * @param the_draft
	 * @return
	 */
	//Stolen from http://stackoverflow.com/questions/1349220/convert-jpanel-to-image 
	//with very little tweeking.
	public static BufferedImage createImage(Observer the_o_ver, Draft the_draft) {
		JPanel drawDown = new DraftPanel(the_o_ver, the_draft).getDrawDown();
		JFrame testframe = new JFrame();
		testframe.add(drawDown);
		testframe.pack();
		
		int w = SIZE*((int)SQUARE_SIZE.getWidth());
		int h = SIZE*((int)SQUARE_SIZE.getHeight());
		BufferedImage bi = new BufferedImage(h, w , BufferedImage.TYPE_INT_RGB);
		Graphics2D g = bi.createGraphics();
		drawDown.paint(g);
		testframe.dispose();
		return bi;
	}
}
